#define ZGRAPHICS_SOURCE
#include "GLUTContext.hpp"
#include "../Graphics/OpenGLTools.hpp"
#include "../Resource/Shader/ShaderSpecify.hpp"

namespace zzz{
GLUTContext * GLUTContext::s_context;
int GLUTContext::window_id;
#ifdef ZZZ_CONTEXT_GLUI
GLUI *GLUTContext::glui;
#endif
GLUTContext::GluiMode GLUTContext::gluimode;

bool GLUTContext::left_;
bool GLUTContext::right_;
bool GLUTContext::middle_;

bool GLUTContext::Initialize(Renderer* renderer, GluiMode mode/*=NOGLUI*/, const char *title/* =0 */, int sizex/* =600 */, int sizey/* =600 */)
{
  s_context=this;
  SetRenderer(renderer);

  left_=false;
  right_=false;
  middle_=false;

  int argc=1;
  char *argv[]={NULL};
#ifdef ZZZ_OPENGL_MX
  OpenGLMutex.Lock();
#endif // ZZZ_OPENGL_MX
  glutInit(&argc,argv);
  glutInitWindowSize(sizex,sizey);
  glutInitWindowPosition(0,0);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
  if (title) window_id=glutCreateWindow(title);
  else window_id=glutCreateWindow("zzz Engine in GLUT");

  MakeCurrent();
  InitGLEW();
  renderer_->InitState();
  renderer_->InitData();
#ifdef ZZZ_OPENGL_MX
  OpenGLMutex.Unlock();
#endif // ZZZ_OPENGL_MX

  glutDisplayFunc(display);
  glutReshapeFunc(reshape);
  glutKeyboardFunc(key);
  glutKeyboardUpFunc(keyup);
  glutSpecialFunc(special);
  glutMouseFunc(mouse);
  glutMouseWheelFunc(mousewheel);
  glutMotionFunc(motion);
  glutPassiveMotionFunc(passivemotion);
//   glutIdleFunc(idle);

  // init GLUI
#ifdef ZZZ_CONTEXT_GLUI
  gluimode = mode;
  switch(mode) {
  case NOGLUI:
    glui=NULL;
    break;
  case GLUISUBWINDOW:
    GLUI_Master.set_glutKeyboardFunc(key);
    GLUI_Master.set_glutSpecialFunc(special);
    GLUI_Master.set_glutMouseFunc(mouse);
    GLUI_Master.set_glutReshapeFunc(reshape);
    GLUI_Master.set_glutIdleFunc(idle);
    glui=GLUI_Master.create_glui_subwindow(window_id,GLUI_SUBWINDOW_RIGHT);
    break;
  case GLUIWINDOW:
    GLUI_Master.set_glutIdleFunc(idle);
    if (title) glui=GLUI_Master.create_glui(title);
    else glui=GLUI_Master.create_glui("zzz Engine GLUI Window",0,sizex+10,0);
    glui->set_main_gfx_window(window_id);
    break;
  }
#endif

  //init GraphicsGUI
  if (gui_) gui_->Init(renderer_);
  return true;
}

GLUTContext::~GLUTContext() {
}

unsigned int GLUTContext::GLUTKey2ZZZKey(int key) {
  switch(key) {
  case GLUT_KEY_F1: return ZZZKEY_F1;
  case GLUT_KEY_F2: return ZZZKEY_F2;
  case GLUT_KEY_F3: return ZZZKEY_F3;
  case GLUT_KEY_F4: return ZZZKEY_F4;
  case GLUT_KEY_F5: return ZZZKEY_F5;
  case GLUT_KEY_F6: return ZZZKEY_F6;
  case GLUT_KEY_F7: return ZZZKEY_F7;
  case GLUT_KEY_F8: return ZZZKEY_F8;
  case GLUT_KEY_F9: return ZZZKEY_F9;
  case GLUT_KEY_F10: return ZZZKEY_F10;
  case GLUT_KEY_F11: return ZZZKEY_F11;
  case GLUT_KEY_F12: return ZZZKEY_F12;
  case GLUT_KEY_LEFT: return ZZZKEY_LEFT;
  case GLUT_KEY_UP: return ZZZKEY_UP;
  case GLUT_KEY_RIGHT: return ZZZKEY_RIGHT;
  case GLUT_KEY_DOWN: return ZZZKEY_DOWN;
  case GLUT_KEY_PAGE_UP: return ZZZKEY_PAGEUP;
  case GLUT_KEY_PAGE_DOWN: return ZZZKEY_PAGEDOWN;
  case GLUT_KEY_HOME: return ZZZKEY_HOME;
  case GLUT_KEY_END: return ZZZKEY_END;
  case GLUT_KEY_INSERT: return ZZZKEY_INSERT;
  }
  return 0;
}

unsigned int GLUTContext::GetInputFlag() {
  int modifers=glutGetModifiers();
  unsigned int flag=0;
  if (CheckBit(modifers,GLUT_ACTIVE_SHIFT)) SetBit(flag,ZZZFLAG_SHIFT);
  if (CheckBit(modifers,GLUT_ACTIVE_ALT)) SetBit(flag,ZZZFLAG_CTRL);
  if (CheckBit(modifers,GLUT_ACTIVE_CTRL)) SetBit(flag,ZZZFLAG_ALT);

  if (left_) SetBit(flag, ZZZFLAG_LMOUSE);
  if (right_) SetBit(flag, ZZZFLAG_RMOUSE);
  if (middle_) SetBit(flag, ZZZFLAG_MMOUSE);
  return flag;
}

}
